/*
 * Copyright (c) 2009 Tim Mead
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Based on the Aggregator (com.adobe.apprise.aggregator.*) code
 * provided in the Apprise AIR sample, by Adobe Systems Incorporated.
 *
 */

package com.misoneism.fire.rssprocessor
{
	import com.adobe.xml.syndication.generic.FeedFactory;
	import com.adobe.xml.syndication.generic.IFeed;
	
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;
	
	public class RSSProcessor
	{
		public function getFeed(responder:RSSProcessorResponder, url:String):void
		{
			// Build up a request to download the RSS feed
			var req:URLRequest = getURLRequest(url);						
			var stream:URLStream = getURLStream(responder);
			
			stream.addEventListener(Event.COMPLETE,
				function():void
				{
					// Download the RSS XML data
					var feedXml:XML;
					try
					{
						var xmlBytes:ByteArray = getDataFromStream(stream);
						feedXml = new XML(xmlBytes);
					}								
					catch (xmlError:Error)
					{
						var xmlErrorEvent:RSSProcessorEvent = new RSSProcessorEvent(RSSProcessorEvent.ERROR_EVENT);
						xmlErrorEvent.data = xmlError.message;
						responder.dispatchEvent(xmlErrorEvent);
						return;
					}
					
					// Parse the XML feed
					var feed:IFeed;
					try
					{
						feed = FeedFactory.getFeedByXML(feedXml);
					}
					catch (feedError:Error)
					{
						var feedErrorEvent:RSSProcessorEvent = new RSSProcessorEvent(RSSProcessorEvent.ERROR_EVENT);
						feedErrorEvent.data = feedError.message;
						responder.dispatchEvent(feedErrorEvent);
						return;
					}
					
					// Fire off the data as an event
					var ae:RSSProcessorEvent = new RSSProcessorEvent(RSSProcessorEvent.FEED_EVENT);
					ae.data = feed;
					responder.dispatchEvent(ae);
				});
				
			// Begin the download
			stream.load(req);
		}
		
		/**
		 * Get a URLRequest object for a given URL
		 */
		private function getURLRequest(url:String):URLRequest
		{
			var req:URLRequest = new URLRequest(url);
			return req;
		}

		/**
		 * Attempt to open a URLStream, and dispatch appropriate
		 * error events if it fails.
		 */
		private function getURLStream(responder:RSSProcessorResponder):URLStream
		{
			var stream:URLStream = new URLStream();
			stream.addEventListener(IOErrorEvent.IO_ERROR,
				function(e:IOErrorEvent):void
				{
					responder.dispatchEvent(e);
				});
			stream.addEventListener(ProgressEvent.PROGRESS,
				function(e:ProgressEvent):void
				{
					responder.dispatchEvent(e);
				});
			stream.addEventListener(Event.COMPLETE,
				function(e:Event):void
				{
					responder.dispatchEvent(e);
				});
			stream.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS,
				function(e:HTTPStatusEvent):void
				{
					responder.dispatchEvent(e);
				});
			return stream;
		}

		/**
		 * Extract the raw data from a URLStream.
		 */
		private function getDataFromStream(stream:URLStream):ByteArray
		{
			var bytes:ByteArray = new ByteArray();
			stream.readBytes(bytes);
			return bytes;
		}
	}
}